/*
 *  Copyright 2008-2010 www.jrails.org
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.rails.core.model.attribute;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;

import org.rails.core.model.ActiveRecord;
import org.rails.core.util.Utils;

public final class BigDecimalAttribute extends AttributeBase {

	private BigDecimal value;

	public BigDecimalAttribute(final ActiveRecord record,final String attriubte) {
		super(record, attriubte);
	}

	@Override
	public void validate() throws AttributeException {
		this.value = parse(inputValue);

		if (isEmpty(this.value))
			this.value = getDefaultValue();
		if (require && Utils.isEmpty(this.value)) {
			throwAttRequireError();
		}
		checkRange();
		if (unique)
			checkUnique();
	}

	@Override
	public BigDecimal getDefaultValue() {
		try {
			return parse(get(DEFAULT_KEY));
		} catch (Exception e) {
			logger.error("Config error : " + this.modAtt + ".default = " + get(DEFAULT_KEY));
			return null;
		}
	}

	@Override
	public BigDecimal getValue() {
		return value;
	}

	@Override
	public BigDecimal getMax() {
		try {
			return parse(get(MAX_KEY));
		} catch (Exception e) {
			logger.error("Config error : " + this.modAtt + ".max = " + get(MAX_KEY));
			return null;
		}
	}

	@Override
	public BigDecimal getMin() {
		try {
			return parse(get(MIN_KEY));
		} catch (Exception e) {
			logger.error("Config error : " + this.modAtt + ".min = " + get(MIN_KEY));
			return null;
		}
	}

	@Override
	public boolean isTrim() {
		return false;
	}

	@Override
	public String format(Object arg) {
		if (Utils.isEmpty(arg)) {
			return "";
		} else {
			return new DecimalFormat(format).format(arg);
		}
	}

	@Override
	public BigDecimal parse(Object arg) throws AttributeException {
		final boolean isFormat = containsKey(FORMAT_KEY);
		if (isEmpty(arg)) {
			return null;
		} else if (arg instanceof Number) {
			return new BigDecimal(arg.toString().trim());
		} else if (arg instanceof String) {
			try {
				return new BigDecimal(arg.toString().trim());					
			} catch (NumberFormatException e) {
				if(isFormat){
					try {
						return new BigDecimal(new DecimalFormat(format).parse(arg.toString().trim()).toString());
					} catch (ParseException e1) {
						throwAttFormatError();
						return null;
					}
				}else{
					throwAttTypeError();
					return null;
				}
			}
		}else {
			throwAttTypeError();
			return null;
		}

	}

	private void checkRange() throws AttributeException {
		if (getMin() != null && !isEmpty(this.value) && value.compareTo(getMin()) == -1) {
			throwAttMinError();
		}
		if (getMax() != null && !isEmpty(this.value) && value.compareTo(getMax()) == 1) {
			throwAttMaxError();
		}
	}

}
